﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Dycox.Reporting;
using Dycox.Reporting.Printing;

namespace Dycox.Windows.Forms
{
    internal partial class ConfirmPaperNotFoundDialog : Form
    {
        PaperNotFoundEventArgs _args;

        public ConfirmPaperNotFoundDialog(PaperNotFoundEventArgs args)
        {
            InitializeComponent();
            pictureBox1.Image = SystemIcons.Exclamation.ToBitmap();

            lbMessage.Text = PopulateMessage(args);

            ReportPageSettings rps = args.Report.PageSettings;
            SizeF size = rps.PaperSize;
            string unit = ReportPrintDocument.GetUnitText(rps.Unit);

            lbPaperName.Text = args.PaperName;
            lbDesiredSize.Text = string.Format("{0}{2} x {1}{2}", size.Width, size.Height, unit);

            PaperSize printerSize = args.PrinterPaperSize;
            if (printerSize != null)
            {
                size = ReportPrintDocument.ConvertSize(printerSize, rps.Unit);
                lbPrinterSize.Text = string.Format("{0}{2} x {1}{2}", size.Width, size.Height, unit);
            }
            else
            {
                lbPrinterSize.Visible = lbPrinterSizeCaption.Visible = false;
            }

            _args = args;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (UacHelper.IsUacAvailable)
                UacHelper.ApplyUacShieldIcon(bnFix.Handle);
        }

        private string PopulateMessage(PaperNotFoundEventArgs e)
        {
            StringBuilder msg = new StringBuilder();

            msg.Append("目前无法正确打印" + e.Report.Name + "，原因是");

            if (e.PrinterPaperSize == null)
            {
                msg.AppendFormat("在打印机“{0}”上没有找到所需的纸张。", e.PrinterName, e.PaperName);
            }
            else
            {
                msg.AppendFormat("在打印机“{0}”上虽然有所需的纸张，但尺寸有差异，可能导致打印结果不正常。", e.PrinterName, e.PaperName);
            }

            return msg.ToString();
        }

        private void bnFix_Click(object sender, EventArgs e)
        {
            int ec;
            if ((ec = Fix()) != 0)
            {
                string msg = "非常抱歉，自动修复失败，请尝试手动修复此问题后再重试。错误代码：" + ec;
                MessageBox.Show(this, msg, null, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                bnRetry_Click(sender, e);
            }
        }

        private void bnRetry_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Retry;
            this.Close();
        }

        private void bnIgnore_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Ignore;
            this.Close();
        }

        private int Fix()
        {
            try
            {
                string path = Path.Combine(Path.GetTempPath(), "PaperSizes.exe");
                using (var fs = File.OpenWrite(path))
                {
                    using (var input = this.GetType().Assembly.GetManifestResourceStream("Dycox.Windows.Resources.PaperSizes.exe"))
                    {
                        input.CopyTo(fs);
                    }
                }

                SizeF size = _args.DesiredPaperSize;
                if (_args.Report.PageSettings.Unit == ReportPageUnit.Centimeter)
                {
                    size.Width *= 10f;
                    size.Height *= 10f;
                }
                ProcessStartInfo info = new ProcessStartInfo(path);
                info.Arguments = string.Format("Add /printer:\"{0}\" /name:\"{1}\" /width:{2} /height:{3} /forced",
                    _args.PrinterName, _args.PaperName, size.Width, size.Height);
                info.WindowStyle = ProcessWindowStyle.Hidden;
                if (UacHelper.IsUacAvailable)
                    info.Verb = "runas";
                info.UseShellExecute = true;

                try
                {
                    Process proc = Process.Start(info);
                    proc.WaitForExit();
                    return proc.ExitCode;
                }
                catch (Win32Exception wex)
                {
                    if (wex.ErrorCode == UacHelper.USER_CANCELLED)
                        return -3;
                    else
                        return -2;
                }
            }
            catch
            {
                return -2;      // unhandled exception
            }
        }
    }
}
